package com.zhoug.widget.customview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewParent;
import android.widget.TextView;

import com.zhoug.widget.R;
import com.zhoug.widget.util.AppUtil;

/**
 * 自定义签名组件
 */
public class SignView extends View {
    private static final String TAG = "SignView";

    /**
     * 签名的画笔
     */
    private Paint mPaint;

    /**
     * 手指按下的x坐标
     */
    private float x;

    /**
     * 手指按下时的y坐标
     */
    private float y;

    /**
     * 签名路径
     */
    private Path path;

    /**
     * 签名图片
     */
    private Bitmap cacheBitmap;

    /**
     * 签名画布
     */
    private Canvas cacheCanvas;

    /**
     * 签名线条宽度 px
     */
    private int paintWidth = 7;
    /**
     * 签名颜色,默认黑色
     */
    private int color = Color.BLACK;

    /**
     * 背景色（指最终签名结果文件的背景颜色，默认为透明色）
     */
    private int backgroundColor = Color.TRANSPARENT;

    /**
     * 是否已经签名
     */
    private boolean isSign = false;

    /**
     * 默认的宽高
     */
    private static final int default_width = 400;
    private static final int default_Height = 400;


    public SignView(Context context) {
        this(context, null);
    }

    public SignView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SignView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SignView);

        color = typedArray.getColor(R.styleable.SignView_color, Color.BLACK);
        backgroundColor = typedArray.getColor(R.styleable.SignView_backgroundColor, Color.TRANSPARENT);
        paintWidth = typedArray.getDimensionPixelSize(R.styleable.SignView_paintWidth, 7);
        typedArray.recycle();

    }

    private void init() {
        if (mPaint == null) {
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setAntiAlias(true);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(paintWidth);
            mPaint.setColor(color);
            path = new Path();
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        init();
        if (cacheBitmap != null) {
            cacheBitmap.recycle();
        }
        cacheBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        cacheCanvas = new Canvas(cacheBitmap);
        cacheCanvas.drawColor(backgroundColor);
        isSign = false;

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int minWidth = getSuggestedMinimumWidth();
        int minHeight = getSuggestedMinimumHeight();

        int width;
        int height;

        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            width = default_width > minWidth ? default_Height : minWidth;
        }

        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            height = default_Height > minHeight ? default_Height : minHeight;
        }

        setMeasuredDimension(width, height);

    }



    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                ViewParent parent = getParent();
                if(parent!=null){
                    parent.requestDisallowInterceptTouchEvent(true);
                }
                //重置路径
                if (!isSign) {
                    isSign = true;
                }
                x = event.getX();
                y = event.getY();
                path.reset();
                path.moveTo(x, y);
//                Log.d(TAG, "onTouchEvent: ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                drawMove(event);
//                Log.d(TAG, "onTouchEvent: ACTION_MOVE");
                break;
            case MotionEvent.ACTION_UP:
                //将路径画到bitmap中，即一次笔画完成才去更新bitmap，而手势轨迹是实时显示在画板上的。
                cacheCanvas.drawPath(path, mPaint);
                path.reset();
//                Log.d(TAG, "onTouchEvent: ACTION_UP");
                break;
        }

        return true;
    }

    /**
     * 画移动轨迹
     *
     * @param event
     */
    private void drawMove(MotionEvent event) {
        //方法一,每次移动手指更新路径然后滑到组件上,弊端:不够平滑,刷新太频繁
       /* float moveX = event.getX();
        float moveY = event.getY();
        path.lineTo(moveX, moveY);
        invalidate();*/
        //方法二,二次贝塞尔，实现平滑曲线
        //最小移动距离
        int scaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
        float moveX = event.getX();
        float moveY = event.getY();
        //求移动距离
        float dis = (float) Math.sqrt(Math.pow(x - moveX, 2) + Math.pow(y - moveY, 2));
        Log.d(TAG, "dis=" + dis);
        if (dis >= scaledTouchSlop) {
            //设置贝塞尔曲线的操作点为起点和终点的一半
            //x, y，cX, cY为终点
            path.quadTo(x, y, (moveX + x) / 2, (moveY + y) / 2);
            x = moveX;
            y = moveY;
            invalidate();
        }

    }


    @Override
    protected void onDraw(Canvas canvas) {
        //画此次笔画之前的签名
        canvas.drawBitmap(cacheBitmap, 0, 0, mPaint);
        // 通过画布绘制多点形成的图形
        canvas.drawPath(path, mPaint);
//        Log.d(TAG, "onDraw: ");
    }

    /**
     * 清除画板
     */
    public void clear() {
        if (cacheCanvas != null) {
            isSign = false;
            //清除
            cacheCanvas.drawColor(backgroundColor, PorterDuff.Mode.CLEAR);
            //重画背景
            cacheCanvas.drawColor(backgroundColor);

            mPaint.setColor(color);
            invalidate();
        }
    }

    /**
     * 获取原图
     *
     * @return
     */
    public Bitmap getBitmap() {

        return cacheBitmap;
    }

    /**
     * 逐行扫描 清楚边界空白。
     *
     * @param blank 保留的边间
     * @return
     */
    public Bitmap getClearBlankBitmap(int blank) {
        if (!isSign) {
            return cacheBitmap;
        }
        int HEIGHT = cacheBitmap.getHeight();
        int WIDTH = cacheBitmap.getWidth();
        int top = 0, left = 0, right = 0, bottom = 0;
        int[] pixs = new int[WIDTH];
        boolean isStop;
        //扫描上边距不等于背景颜色的第一个点
        for (int y = 0; y < HEIGHT; y++) {
            cacheBitmap.getPixels(pixs, 0, WIDTH, 0, y, WIDTH, 1);
            isStop = false;
            for (int pix : pixs) {
                if (pix != backgroundColor) {
                    top = y;
                    isStop = true;
                    break;
                }
            }
            if (isStop) {
                break;
            }
        }
        //扫描下边距不等于背景颜色的第一个点
        for (int y = HEIGHT - 1; y >= 0; y--) {
            cacheBitmap.getPixels(pixs, 0, WIDTH, 0, y, WIDTH, 1);
            isStop = false;
            for (int pix : pixs) {
                if (pix != backgroundColor) {
                    bottom = y;
                    isStop = true;
                    break;
                }
            }
            if (isStop) {
                break;
            }
        }
        pixs = new int[HEIGHT];
        //扫描左边距不等于背景颜色的第一个点
        for (int x = 0; x < WIDTH; x++) {
            cacheBitmap.getPixels(pixs, 0, 1, x, 0, 1, HEIGHT);
            isStop = false;
            for (int pix : pixs) {
                if (pix != backgroundColor) {
                    left = x;
                    isStop = true;
                    break;
                }
            }
            if (isStop) {
                break;
            }
        }
        //扫描右边距不等于背景颜色的第一个点
        for (int x = WIDTH - 1; x > 0; x--) {
            cacheBitmap.getPixels(pixs, 0, 1, x, 0, 1, HEIGHT);
            isStop = false;
            for (int pix : pixs) {
                if (pix != backgroundColor) {
                    right = x;
                    isStop = true;
                    break;
                }
            }
            if (isStop) {
                break;
            }
        }
        if (blank < 0) {
            blank = 0;
        }
        //计算加上保留空白距离之后的图像大小
        left = left - blank > 0 ? left - blank : 0;
        top = top - blank > 0 ? top - blank : 0;
        right = right + blank > WIDTH - 1 ? WIDTH - 1 : right + blank;
        bottom = bottom + blank > HEIGHT - 1 ? HEIGHT - 1 : bottom + blank;
        return Bitmap.createBitmap(cacheBitmap, left, top, right - left, bottom - top);

    }


    public void setPaintWidth(int paintWidthDip) {
        this.paintWidth = AppUtil.dipTopx(getContext(), paintWidthDip);
    }

    public void setColor(int color) {
        this.color = color;
    }

    @Override
    public void setBackgroundColor(int backgroundColor) {
        this.backgroundColor = backgroundColor;
    }

}
